import React, {Component} from 'react';
import CanvasSvg from "./canvasSVG";
import {getTree} from "./fib2";
import Menu from "./menu";
import Navbar from "./navbar";
import {MinHeap} from "./Heap";
import $ from "jquery"
import {r, randomList, svgHeight, svgWidth, xBias, xTimes, yBias, yTimes} from "./Const";
import CustomizedTables from "./table"
import GRAPH from "./help/GRAPH";
import TableForDijkstra from "./tableForDijkstra";
import TableForPrim from "./tableForPrim";
import TableForKruskal from "./tableForKruskal";
import {graph_random} from "../ForceEnum/Const";


let tree;
let before = false;
let pause = false;
let reset = false;
// s 是字符串
const checkNumber = (s) => {
    return Number(s, 10).toString() === s;
}

class Graph extends Component {
    constructor() {
        super();
        this.state = {
            reset: false,
            vertices: [],
            edges: [],
            current: -1,
            nrFlag: true,
            redNumber: -1,
            algo: 0,
            offset: 0,
            animation_stop: true,
            time: 500,
            leftMost: undefined,
            rightMost: undefined,
            upMost: undefined,
            downMost: undefined,
            width: undefined,
            height: undefined,
            // 随机选择的num
            selectNum: 0,
            // 最多可以选择到多少N
            MaxN: 11,

            select: false,

            setGreenFlag: false,


            // 关于huffman table
            listNHuffman: [],
            listResHuffman: [],
            nowIndexHuffman: -1,
            // 图
            nodes:[],
            changed: false,
            // 关于 dijkstra table
            from: 0,
            nowSelectedNode: -1,
            // 0 代表 selected， 1 代表 visiting， 2 代表 visited
            edgeVisitState: -1,
            edgeIndex: -1,
            repaint: false,

            // dijkstra
            listV: [],
            final: [],
            dist: [],
            path: {},
            selectDirect: false,

            // prim
            isJoin: [],
            lowCost: [],

            // kruskal
            sortEdge: [],
            nowEdge: -1
        }

        this.nodes = [];
        this.edges = [];
        this.directedGraph = {};
        this.input = [];
    }


    handlePaused = (flag) => {
        // this.setState({isPaused: flag});
        before = pause;
        pause = flag;
    }

    handlePausedForLoop = () => {
        before = false;
        pause = true;
    }

    handleDirect = async (select) => {
        await this.realOnReset();
        this.setState({selectDirect: select});
        await sleep(1);
        await this.handleDraw();

    }

    handleFrom = (val) => {
        this.setState({from: val});
    }

    handleGenerate = async () => {
        let inputElement;
        this.realOnReset();
        let algo = this.state.algo;

        if (algo === 3) {
            {
                inputElement = $("#input");
                let [list, key] = randomList(algo);
                inputElement.val(list.reduce((a, b) => {
                    return a + "," + b;
                }));
            }
        } else {
            inputElement= $("#input");
            let random = Math.floor(Math.random() * graph_random.length);
            inputElement.val(graph_random[random]);
            await this.handleDraw();
        }
    }

    handleSpeed = (speed) => {
        let time;
        if (speed >= 80) {
            time = 900 - 9 * speed + 1;
        }
        else {
            time = 1800 - 8 * speed;
        }
        this.setState({time})
    }

    changeSelect = () => {
        let select = !this.state.select;
        this.setState({select});
    }

    realOnReset = async () => {
        pause = true;

        this.changeSelect();
        this.onReset();
        this.setState({changed: !this.state.changed});

        await sleep(1);
    }

    onReset = () => {
        pause = true;

        this.setState({reset: true, setGreenFlag: false, vertices: [], edges: [],
            listNHuffman: [],
            listResHuffman: [],
            nowIndexHuffman: -1,


            // 关于 dijkstra table
            from: 0,
            nowSelectedNode: -1,
            // 0 代表 selected， 1 代表 visiting， 2 代表 visited
            edgeVisitState: -1,
            edgeIndex: -1,

            // dijkstra
            listV: [],
            final: [],
            dist: [],
            path: {},

            // prim
            isJoin: [],
            lowCost: [],

            // kruskal
            sortEdge: [],
            nowEdge: -1

        });

        reset = true;
        this.state.vertices = [];

        $("#img").css({
                        scale: "1",
                        transform: "scale(1)",
                        left: "0",
                        top: "10px",
                      });
        pause = before = false;
    }

    // 执行去除tab和空格的操作
    clearPure = (string) => {
        let final = "";
        for (let i = 0; i < string.length; i++) {
            if (string[i] !== " " || string[i] !== "\t")
                final += string[i];
        }
        return final;
    }

    clearTabSpace = (string) => {
        let final = this.clearPure(string);
        return final.split(",").map((value) => parseInt(value));
    }

    sort = (string) => {
        return string.sort((a,b) => a-b);
    }

    handleDraw = async () => {
        await this.handleInput();
        await sleep(1);

        this.setState({changed: !this.state.changed});
    }

    handleVertexEdges = (array, nodes, edges) => {
        let temp = [...array];
        temp.splice(0, 1);
        let total = {};

        const inArray = (point, total, nodes) => {
            if (!(point in total)) {
                total[point] = 1;
                nodes.push({
                    id: `node${point}`,
                    value: point,
                    label: `V${point}`
                });
            }
        }

        let directedGraph = {};
        const checkEdgeNotIn = (src, dst, edges)=>{
            for (let i = 0; i < edges.length; i++) {
                if ((`node${src}` === edges[i].source && `node${dst}` === edges[i].target)
                || (`node${dst}` === edges[i].source && `node${src}` === edges[i].target) )
                    return false;
            }
            return true;

        };

        for(let item of temp) {
            let src = item[0];
            let dst = item[1];
            let weight = item[2];
            inArray(src, total, nodes);
            inArray(dst, total, nodes);
            if (this.state.selectDirect) {
                if (checkEdgeNotIn(src, dst, edges))
                edges.push({
            source: `node${src}`,
            target: `node${dst}`,
            label: String(weight),
        });
            } else {
                edges.push({
            source: `node${src}`,
            target: `node${dst}`,
            label: String(weight),
        });
            }
        }

        for (let i = 0; i < edges.length; i++) {
            let src = parseInt(edges[i].source.substring(4));
            let dst = parseInt(edges[i].target.substring(4));
            let weight = parseInt(edges[i].label);
             if (!(dst in directedGraph)) {
                directedGraph[dst] = [];
            }

            if (!(src in directedGraph)) {
                directedGraph[src] = [];
            }

            if (this.state.selectDirect)
                directedGraph[dst].push([src,weight, i]);
            directedGraph[src].push([dst, weight, i]);

        }

        directedGraph = {...directedGraph};
        this.directedGraph = directedGraph;
    }


    handleGraphInput = async (value) => {
        let valueArray = value.split("\n");
        valueArray = valueArray.map(x=>x.split(/[\t ]+/).map(x=>parseInt(x)));
        let vertexCount = valueArray[0][0];
        let edgeCount = valueArray[0][1];
        let nodes = [];
        let edges = [];
        this.handleVertexEdges(valueArray, nodes, edges);
        nodes.sort((a,b)=>a.value-b.value);
        this.nodes = [...nodes];
        this.edges = [...edges];
        await sleep(1);
    }

    handleInput = async () => {
        try {
            let inputElement = document.getElementById("input");
            if (this.state.algo === 3) {
                let input = this.sort(this.clearTabSpace(inputElement.value));
            inputElement.value = input;
            this.input = input;
            } else {
                await this.handleGraphInput(inputElement.value);
            }

        } catch (e) {

        }

    }


    setAlgo = async (pos, val) => {
        if (pos === 0) {
            await this.realOnReset();
            this.setState({algo: val, nrFlag: val === 0});
            if (val === 1 || val === 2) {
                this.setState({selectDirect: true});
                await sleep(2);
                await this.handleDraw();
            } else if (val === 0 ) {
                this.setState({selectDirect: false});
                await sleep(1);
                await this.handleDraw();
            }

        }
    }

    setN = (pos, val) => {
        if (pos === 0) {
            this.setState({n: val});
        }
    }

    setR = (pos, val) => {
        if (pos === 0) {
            this.setState({r: val});
        }
    }
    addNumber = async ()=>{
        if (before) {

        }
        else {
        this.onReset();
        if (this.state.algo !== 3) {
                this.setState({repaint: !this.state.repaint})
            }
        else {
            this.setState({redNumber: -1});
            if (this.state.reset) {
                this.onReset();
                await this.addNumberTemp();
                }
        }

        await this.addNumberTemp();
        this.changeSelect();
        pause = before = false;
        }


    }

    transForDraw = (tree, rootBias) => {
        tree.x = (tree.x - rootBias) * xTimes;
        tree.y = tree.y * yTimes + yBias;
        if (tree.left) {
            this.transForDraw(tree.left, rootBias);
        }
        if (tree.right) {
            this.transForDraw(tree.right, rootBias);
        }
    }

    transForLeftX = (tree, bias) => {
        tree.x += bias;
        if (tree.left) {
            this.transForLeftX(tree.left, bias);
        }
        if (tree.right) {
            this.transForLeftX(tree.right, bias);
        }
    }

    addNumberTemp = async () => {
            if (this.state.algo === 3) {
                await this.handleInput();
                tree = getTree(this.state.n,this.state.algo,this.state.r, [...this.input]);
                this.transForDraw(tree, tree.x);

                let leftMost = tree.getMostLeft(tree).x;
                if (leftMost - 2 * r < 0) {
                    this.transForLeftX(tree, -leftMost + 2 * r);
                }

                leftMost = tree.getMostLeft(tree).x;

                let rightMost = tree.getMostRight(tree).x;
                let upMost = tree.y;
                let downMost = tree.getMostY(tree);
                let width = rightMost - leftMost + 4 * r;
                let height = downMost - upMost + 4 * r;

                this.setState({
                    width,
                    height
                    });

                this.setState({edges:[],vertices:[], offset:tree.x, reset: false, animation_stop:false});
                reset = false;
                this.state.vertices = [];
                await this.recurHuffman(tree);
            }
            else {

                this.setState({reset: false});
                reset = false;

                // await this.handleInput();
                if (this.state.algo === 0) {
                    this.changeSelect();
                    this.handlePausedForLoop();
                    await this.dijkstra();
                } else if (this.state.algo === 2) {
                    this.changeSelect();
                    this.handlePausedForLoop();
                    await this.prim();
                } else {
                    this.changeSelect();
                    this.handlePausedForLoop();
                    await this.kruskal();
                }
            }
    }

     kruskal = async() => {
         let copyEdges = [];
         for (let i = 0; i < this.edges.length; i ++) {
             let nowEdge = this.edges[i];
             copyEdges.push([parseInt(nowEdge.source.substring(4)),
                            parseInt(nowEdge.target.substring(4)),
                            parseInt(nowEdge.label),
                            i
             ]);
         }
         copyEdges.sort((a, b)=>a[2]-b[2]);

         let toTableEdges = [];
         for (let item of copyEdges) {
             toTableEdges.push([item[2], item[0], item[1]]);
         }

         this.setState({listV: ["Weight", "Vertex1", "Vertex2"], sortEdge: [...toTableEdges]});

         let p = new Array(this.nodes.length).fill(-1);
         for (let i = 0; i < p.length; i ++) {
             p[i] = i;
         }
         const find = (x) => {
                            if(x !== p[x]) p[x] = find(p[x]);
                            return p[x];
                            };



         const findNodeOrder = (value) => {
             for (let i = 0; i < this.nodes.length; i++) {
                 if (this.nodes[i].value === value) {
                     return i;
                 }
             }
         }

         let processedQueue = [];

         const inQueue = (id) => {
             if (id in processedQueue)
                 return false;
             processedQueue.push(id);
             return true;
         }
         for (let i = 0; i < copyEdges.length; i++) {
             let edge = copyEdges[i];
             let [v1, v2, weight, edgeIndex] = edge;
             this.setState({nowEdge: i});
             await sleep(this.state.time);
             this.setState({edgeVisitState: 1, edgeIndex});
             await sleep(this.state.time);

             let id1 = findNodeOrder(v1);
             let id2 = findNodeOrder(v2);
             if (inQueue(id1)) {
                 this.setState({nowSelectedNode: id1});
                 await sleep(this.state.time);
             }
             if (inQueue(id2)) {
                 this.setState({nowSelectedNode: id2});
                 await sleep(this.state.time);
             }

             let p1 = find(id1);
             let p2 = find(id2);
             if (p1 !== p2) {
                p[p1] = p2;
                this.setState({edgeVisitState: 0, edgeIndex});
             } else {
                this.setState({edgeVisitState: 2, edgeIndex});
             }

             this.handlePausedForLoop();
             this.changeSelect();

         }




    }

    prim = async (at=0) => {
        let vertices = [];
        let isJoin = [];
        let lowCost = [];
        let visited = new Map();
        for (let item of this.nodes) {
            visited.set(item.value, false);
            vertices.push(item.label);
            isJoin.push(false);
            lowCost.push("∞");
        }

        lowCost[0] = 0;
        this.setState({listV: [...vertices], isJoin: [...isJoin], lowCost: [...lowCost]});


        let visitedTransferred = [];

        for (let [key, _] of visited) {
            visitedTransferred.push(key);
        }
        let v = visitedTransferred.length;


        visited.set(visitedTransferred[0], true);


        isJoin[0] = true;

        this.setState({nowSelectedNode: 0});
        await sleep(this.state.time);
        this.setState({isJoin: [...isJoin]});

        let directedGraph = {...this.directedGraph};

        const findElement = (value) => {
            for (let i = 0; i < v; i++) {
                if (value === visitedTransferred[i])
                    return i;
            }
        }


        const getMin = () => {
            let min = Number.MAX_VALUE - 1;
            let indexMin = -1;
            let edgeMin = -1;
            console.log(visited)
            for (let [key, value] of visited) {
                if (value) {
                    let dGroup = directedGraph[key];
                    console.log(dGroup)
                    for (let item of dGroup) {
                        let [to, w, edgeIndex] = item;
                        if (!visited.get(to) && w < min) {
                            min = w;
                            indexMin = to;
                            edgeMin = edgeIndex;
                        }

                    }
                }
            }

            return [min, findElement(indexMin), edgeMin];
        }
        const checkAll = () => {
            for (let [_, value] of visited)
                if (!value) return false;
            return true;
        }


        while (!checkAll()) {
            let [minCost, index, edgeIndex] = getMin();
            this.setState({edgeVisitState: 0, edgeIndex});
            await sleep(this.state.time);
            this.setState({nowSelectedNode: index});
            await sleep(this.state.time);
            isJoin[index] = true;
            this.setState({isJoin: [...isJoin]})
            await sleep(this.state.time);
            lowCost[index] = minCost;
            this.setState({lowCost: [...lowCost]});
            await sleep(this.state.time);
            visited.set(visitedTransferred[index], true);

            this.handlePausedForLoop();
            this.changeSelect();
            await sleep(this.state.time);
        }

    }

    stateAwait = async () => {
        await sleep(1);
    }

    setCustomState = async (d, mode=0) => {
        this.setState(d);
        if (mode === 0)
            await this.stateAwait();
        else
            await sleep(mode);
    }

    dijkstra = async (at = 0) => {
        function minimum(visited, distance, visitedTransferred) {
            let counter = 0;
            let min = -1;

            while (counter !== visited.size) {
                if (min === -1 && !visited[visitedTransferred[counter]]) {
                    min = counter;
                } else {
                    if (!visited[visitedTransferred[counter]] && distance[min][0] > distance[counter][0]) {
                        min = counter;
                    }
                }
                counter++;
            }

            return min;
        }


        let listV = [];
        let final = [];
        let dist = [];
        let tempPath = [];
        let visited = new Map();
        for (let item of this.nodes) {
            visited.set(item.value, false);
            listV.push(item.label);
            final.push(false);
            dist.push("∞");
            tempPath.push(-1);
        }

        dist[0] = 0;

        this.setState({headName: "Vertex",listV: [...listV], final: [...final], dist: [...dist], path: [...tempPath]});
        await sleep(this.state.time);

        let visitedTransferred = [];


        for (let [key, _] of visited) {
            visitedTransferred.push(key);
        }
        let v = visitedTransferred.length;

        const findElement = (value) => {
            for (let i = 0; i < v; i ++) {
                if (value === visitedTransferred[i])
                    return i;
            }
        }

        let distance = new Array(v).fill([Number.MAX_VALUE, -1]);
        distance[visitedTransferred[at]] = [0, -1];
        let count = 0;
        // markAllEdgesVisited();
            let directedGraph = {...this.directedGraph};
            let path = [];
            for (let i = 0; i < v; i++) {
                path[i] = -1;
            }
            let visitedEdges = [];
        while (count !== v ) {
            let min = minimum(visited, distance, visitedTransferred); // Minimum non-visited node
            visited[visitedTransferred[min]] = true;
            final[min] = true;

            await this.setCustomState({nowSelectedNode: min}, this.state.time);

            await this.setCustomState({final: [...final]}, this.state.time);
            count++;

            for (let i = 0; i < directedGraph[visitedTransferred[min]].length; i++) {
                let [to, w, edgeIndex] = directedGraph[visitedTransferred[min]][i];
                let newValue = distance[min][0] + w;

                 if (visitedEdges.indexOf(edgeIndex) === -1)
                 {

                     await this.setCustomState({edgeVisitState: 1, edgeIndex}, this.state.time);
                    if (distance[to][0] > newValue ) {
                        path[findElement(to)] = "V" + visitedTransferred[min];
                        dist[findElement(to)] = newValue;
                        await this.setCustomState({path: [...path], dist: [...dist]}, this.state.time);
                        let oldEdge = distance[to][1];

                        if (oldEdge !== -1 ) {
                            // visitedEdges.push(oldEdge);
                            await this.setCustomState({edgeVisitState: 2, edgeIndex: oldEdge}, this.state.time);
                        }

                        distance[to] = [newValue, edgeIndex];

                        await this.setCustomState({edgeVisitState: 0, edgeIndex}, this.state.time);

                    } else {
                            await this.setCustomState({edgeVisitState: 2, edgeIndex}, this.state.time);
                    }
                    visitedEdges.push(edgeIndex);
                }


            }
            this.changeSelect();
            this.handlePausedForLoop();
        }
}


    // 这里出现bug的原因是 节点顺序设置错误
    recurHuffmanDraw = async (tree1, tree2, visited) => {

        if (!this.state.reset) {
            let parent = tree1.parent;
            let treeList = [tree1, tree2];
            let vertices = [...this.state.vertices];
            for (let i = 0; i < treeList.length; i++) {
                let current = treeList[i].getId();
                if (!visited[current]) {
                    vertices.push({label:treeList[i].tree.label.split(",")[0],val:0,
                        x:treeList[i].x,y:treeList[i].y,px:treeList[i].x,py:treeList[i].y,
                        isLeaf: treeList[i].isLeaf});
                    visited[treeList[i].getId()] = true;
                    if (this.state.reset) return false;this.setState({vertices});

                }
                    if (this.state.reset) return false;this.setState({vertices, current});
                    await sleep(this.state.time);
            }

            for (let i = 0; i < treeList.length; i++) {
                let edges = this.state.edges;
                edges.push({
                    x1: treeList[i].x,
                    y1: treeList[i].y,
                    x2: parent.x,
                    y2: parent.y
                });
                if (this.state.reset) return false;this.setState({edges});
            }

            if (!visited[parent.id]) {
                vertices.push({label:parent.tree.label.split(",")[0],val:0,
                        x:parent.x,y:parent.y,px:parent.x,py:parent.y});
                    visited[parent.getId()] = true;
                    if (this.state.reset) return false;this.setState({vertices});
            }
            let current = parent.id;
            if (this.state.reset) return false;this.setState({vertices, current});
            await sleep(this.state.time);
        }
        return true;
    }

    generateN = (n, bias=0) => {
        let list = [];
        for (let i = 0; i < n; i++) {
            list.push(i + bias);
        }
        return list;
    }

    findInsertPos = (key, list) => {
                let length = list.length;
                let nowPos = 1;
                while (nowPos < length && list[nowPos] < key) nowPos ++;
                if (nowPos === length  || list[nowPos] > key)
                    return nowPos - 1;
                return nowPos;
            }

    recurHuffman = async (node) => {
        try {

            let treeHeap = new MinHeap();
            let queue = [];
            queue.push(node);

            while (!this.state.reset && queue.length !== 0) {
                let [head] = queue.splice(0, 1);
                treeHeap.insert(head);
                if (head.left) {
                    queue.push(head.left);
                }
                if (head.right) {
                    queue.push(head.right);
                }

            }

            let heap = [...treeHeap.getAll()];

            let visited = {}
            for (let i = 0; !this.state.reset && i < heap.length; i++) {
                visited[heap[i].getId()] = false;
            }

            let flag = true;
            let input = [...this.input.map(x=>parseInt(x))];


            let listRes = [...input];
            while (!this.state.reset && flag && treeHeap.getLength() !== 1) {
                let tree1 = treeHeap.pop();
                let tree2 = treeHeap.pop();
                listRes = [...listRes];
                let length = listRes.length;
                let listN = this.generateN(length);

                // 表格的逻辑 1
                {

                    await sleep(this.state.time);
                    this.setState({listNHuffman: [...listN],
                                        listResHuffman: [...listRes],
                                        nowIndexHuffman: 1});
                    await sleep(this.state.time);
                }

                await (flag = this.recurHuffmanDraw(tree1, tree2, visited));


                // 表格的逻辑2
                if (treeHeap.getLength() !== 1)
                {

                    let newValue = listRes[0] + listRes[1];

                    listRes.splice(0, 2);


                    listRes.splice(0, 0, newValue);
                    listN = this.generateN(listRes.length);
                    await sleep(this.state.time);
                    this.setState({listNHuffman:[...listN],
                                        listResHuffman: [...listRes],
                                        nowIndexHuffman: 0
                    });



                    let findPos = this.findInsertPos(newValue, listRes);
                    await sleep(this.state.time);

                    this.setState({nowIndexHuffman: findPos})
                    await sleep(this.state.time);

                    listRes.sort((a,b)=>a-b);

                    this.setState({listResHuffman: [...listRes],
                                        })
                    await sleep(this.state.time);

                }
            }
            if (flag ) {
                let vertices = [...this.state.vertices];
                let parent = treeHeap.peek();
                vertices.push({label:parent.tree.label.split(",")[0],val:0,
                        x:parent.x,y:parent.y,px:parent.x,py:parent.y});
             !this.state.reset && this.setState({vertices});


                {
                    let newValue = listRes[0] + listRes[1];

                    listRes.splice(0, 2);


                    listRes.splice(0, 0, newValue);
                    let listN = this.generateN(listRes.length);
                    await sleep(this.state.time);
                    this.setState({listNHuffman:[...listN],
                                        listResHuffman: [...listRes],
                                        nowIndexHuffman: 0
                    });
                    await sleep(this.state.time);
                }

             !this.state.reset && this.setState({setGreenFlag: true});
                await sleep(this.state.time * 2);
            }


        } catch (e) {
        }

    }

    algoDisplay = () => {
        let display;

        if (this.state.algo === 3) {
            display =  (
                <React.Fragment>
                    <CanvasSvg

                    width = {this.state.width}
                    height = {this.state.height}
                    flagForDraw = {this.state.flagForDraw}
                    setGreenFlag = {this.state.setGreenFlag}

                    algorithm = {this.props.algo}
                    time = {this.state.time}
                    N = {this.state.n}
                    vertices={this.state.vertices}
                    edges={this.state.edges}
                    current={this.state.current}
                    offset={this.state.offset}
                    reset = {this.state.reset}
                    animation_stop = {this.state.animation_stop}
                    nrFlag = {this.state.nrFlag}
                    redNumber = {this.state.redNumber}
                />
               <CustomizedTables

                   reset = {this.state.reset}
                  tableId = "huffmanTable"
                  headName = "Index"
                  bodyName = "Frequency"
                  tableName = "Not calculated table"
                  listN = {this.state.listNHuffman}
                  listRes = {this.state.listResHuffman}
                  nowIndexRes= {this.state.nowIndexHuffman}
               />
                </React.Fragment>
            )
        } else {
            let table;
            if (this.state.algo === 0) {
                table = <TableForDijkstra
                                listN={this.state.listV}
                                final={this.state.final}
                                dist={this.state.dist}
                                path={this.state.path}
                                reset={reset}
                            />;
            }
            else if (this.state.algo === 2) {
                table = <TableForPrim
                       listN = {this.state.listV}
                       isJoin = {this.state.isJoin}
                       lowCost = {this.state.lowCost}
                       reset = {reset}
                />;
            } else {
                table = <TableForKruskal
                        listN = {this.state.listV}
                        sortEdge = {[...this.state.sortEdge]}
                        nowEdge = {this.state.nowEdge}
                />
            }
            display = (
                <div className="row" style={{height: "calc(100vh - 120px)"}}>
                    <div className="col-6 left-panel d-flex justify-content-center align-items-center" id="left-panel">
                        <GRAPH
                        nodes = {this.nodes}
                        edeges = {this.edges}
                        changed = {this.state.changed}
                        nowSelectedNode = {this.state.nowSelectedNode}
                        edgeVisitState = {this.state.edgeVisitState}
                        edgeIndex = {this.state.edgeIndex}
                        repaint = {this.state.repaint}
                        reset = {reset}
                        selectDirect = {this.state.selectDirect}
                        algo = {this.state.algo}
                        />
                    </div>

                    <div className="col-6 border-end p-3 align-self-center" id="right-panel">
                        <div className="mt-3">
                            {table}
                        </div>
                    </div>
                </div>
            )

    //        $(function(){
    //            $("#dijkstraTable").draggable({containment: "body"});
    // });

        }

        return display;
    }


    render = () =>  {
        // $('body').css({"overflow-x": "hidden"});
        return (
            <div style={{
                overflow: "hidden",
                }}>
                <Navbar
                    name={"Greedy"}
                />
                <Menu
                    handlePaused = {this.handlePaused}
                    select = {this.state.select}

                    onChange = {this.realOnReset}

                    handleDirect = {this.handleDirect}

                    MaxN = {this.state.MaxN}
                    selectNum = {this.state.selectNum}
                    onGenerate = {this.handleGenerate}
                    algo={this.state.algo}
                    handleSpeed = {this.handleSpeed}
                    setN={this.setN}
                    setR={this.setR}
                    setAlgo={this.setAlgo}
                    onStart={this.addNumber}
                    onReset={this.realOnReset}
                    // 图
                    handleDraw = {this.handleDraw}

                    // 给dijkstra 提供的
                    handleFrom = {this.handleFrom}
                    from = {this.state.from}
                    nodes = {this.state.nodes}

                />

                {this.algoDisplay()}

            </div>
        );
    }
}

// const requestAnimationFrame = window.requestAnimationFrame
// || window.mozRequestAnimationFram
// || window.webkitRequestAnimationFrame
// || window.msRequestAnimationFrame
// || function(callback){ window.setTimeout(callback, 1000/ 60)}

const cancelAnimationFrame = window.cancelAnimationFrame
|| window.mozCancelAnimationFrame;

let allRef = null;

function animateTimeout(cb,time){

	let i = 0;

    let myRef = null;
    let rememberTime = time;
	myRef = requestAnimationFrame(function fn(){
        if (pause)
            time = 100000000000;
        else
            time = rememberTime;
		if(i > Math.floor(60 / (1000/time)) || reset){
			cb();
			cancelAnimationFrame(myRef);
            // return ;
		}
		i++;

		myRef = requestAnimationFrame(fn)
	})
}


function sleep(ms) {
    return new Promise(resolve => animateTimeout(resolve, ms));
}
export default Graph;